package pl.koszolko.documentclustering.dao;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class Document implements Comparable<Document>, Serializable {
	private static final long serialVersionUID = 1L;
	
	private Long id;
	private String documentClass;
	private String title;
	private String abstractText;
	private List<Author> authors;

	private Set<Document> references;
	private Set<Document> citedBy;

	public Document() {
		authors = new ArrayList<Author>();
		references = new TreeSet<Document>();
		citedBy = new TreeSet<Document>();
	}
	
	public void setId(Long id) {
		this.id = id;
	}

	public Long getId() {
		return id;
	}

	public String getDocumentClass() {
		return documentClass;
	}

	public void setDocumentClass(String documentClass) {
		this.documentClass = documentClass;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getAbstractText() {
		return abstractText;
	}

	public void setAbstractText(String abstractText) {
		this.abstractText = abstractText;
	}

	public List<Author> getAuthors() {
		return authors;
	}

	public void setAuthors(List<Author> authors) {
		this.authors = authors;
	}

	public Set<Document> getReferences() {
		return references;
	}

	public void setReferences(Set<Document> references) {
		this.references = references;
	}

	public void setCitedBy(Set<Document> citedBy) {
		this.citedBy = citedBy;
	}

	public Set<Document> getCitedBy() {
		return citedBy;
	}
	
	public void addCitedBy(Document doc) {
		citedBy.add(doc);
	}
	
	public void addReference(Document doc) {
		references.add(doc);
	}
	
	public int getReferencesSize() {
		return references.size();
	}
	
	public boolean ifReferencesContains(Document doc) {
		return references.contains(doc);
	}
	
	public int getCitedBySize() {
		return citedBy.size();
	}
	
	public boolean ifCitedByContains(Document doc) {
		return citedBy.contains(doc);
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Document other = (Document) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	public Double countDistance(Document doc) {
		double allReferences = 0;
		double wspolneREferences = 0;
		
		allReferences = references.size();
		
		for(Document docRef : doc.getReferences()) {
			if(references.contains(docRef)) {
				++wspolneREferences;
			} else {
				++allReferences;
			}
		}
		
		if(allReferences == 0)
			return 0D;
		else
			return wspolneREferences/allReferences;
	}

	@Override
	public int compareTo(Document document) {
		return (int) (id - document.getId());
	}

	public void addAuthor(Author aut) {
		authors.add(aut);
	}
}
